#pragma once
// model通常是用来做数据交换的模块

#include <iostream>

#include <string>
#include <unordered_map>
#include <vector>
#include <cassert>
#include<cstdlib>
#include <fstream>

#include<algorithm>
#include "../Comm/Util.hpp"
#include "../Comm/Log.hpp"

using namespace ns_util;
using namespace ns_log;
namespace ns_model
{
    struct Questions
    {
        std::string number; // 题目编号
        std::string title;  // 标题
        std::string star;   // 难度:简单 中等 困难
        int cup_limit;      // 时间要求
        int mem_limit;      // 空间要求
        std::string desc;   // 题目描述
        std::string header; // 题目预设
        std::string tail;   // 测试用例
    };
    const std::string questions_list = "./questions/question.list";
    const std::string question_path="./questions/";
    class Model
    {

    public:
        Model()
        {
            assert(LoadownQuestionList(questions_list));
        }
        ~Model()
        {
        }
        bool LoadownQuestionList(const std::string question_list) // 加载题目列表
        {
            std::ifstream in(question_list);
            if (!in.is_open())
            {
                LOG(FATAL)<<"加载题库失败,请检查题库是否存在"<<"\n";
                return false;
            }
            std::string line;
            while (std::getline(in, line))
            {
                // 1 判断回文 简单 1 3000
                std::vector<std::string> tokens;
                SplitUtil::StringSplit(line,&tokens," ");
                if(tokens.size()!=5)
                {
                    LOG(WARNING)<<"加载部分题库失败,请检查题库格式"<<"\n";
                    return false;
                }
                struct Questions q;
                q.number=tokens[0];
                q.title=tokens[1];
                q.star=tokens[2];
                q.cup_limit=std::atoi(tokens[3].c_str());
                q.mem_limit=std::atoi(tokens[4].c_str());

                //./questions/+number+文件名
                std::string path=question_path;
                path+=q.number;
                path+="/";
                Fileutil::Readfile(path+"desc.txt",&(q.desc),true);
                Fileutil::Readfile(path+"header.cpp",&(q.header),true);
                Fileutil::Readfile(path+"tail.cpp",&(q.tail),true);
                question.insert({q.number,q});
            }
            LOG(INFO)<<"加载题库....成功"<<"\n";
            in.close();
            return true;
        }
        bool QuestionAll(std::vector<struct Questions> *out) // 获取所有题目
        {
            if (question.empty())
            {
                LOG(WARNING)<<"用户加载题库失败"<<"\n";
                return false;
            }
        
            for (auto &e : question)
            {
                out->push_back(e.second);
            }
            return true;
        }
        bool QuestionOne(std::string number, struct Questions *q) // 获取单道题目
        {
            const auto &ater = question.find(number);
            if (ater == question.end())
            {
                LOG(ERROR)<<"用户加载题目失败,编号为:"<<number<<"\n";
                return false;
            }
            (*q) = ater->second;
            return true;
        }

    private:
        // 题号：题目信息
        std::unordered_map<std::string,struct Questions> question;
    };
}